package se.webbzon.boltzmann.minigame.effect;

import java.awt.Rectangle;

import se.webbzon.boltzmann.minigame.sandbox.DefaultSandBoxItem;
import se.webbzon.boltzmann.minigame.sandbox.SandBox;
import se.webbzon.boltzmann.minigame.sandbox.SandBoxIcon;
import se.webbzon.boltzmann.minigame.sandbox.SandBoxItem;
import se.webbzon.boltzmann.minigame.sandbox.SandBoxObject;
import se.webbzon.boltzmann.resource.Resources;
import se.webbzon.oschi01.resourceset.ResourceSet;
import se.webbzon.oschi01.textureset.Texture3D;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldcamera.WorldCameraPane;
import se.webbzon.oschi01.worldobject.WorldObject;

public class SandBoxRain extends DefaultSandBoxItem {
	
	// The 2-dimensional depth of the rain
	private static final int depth = 175;
	
	// The default intensity of the rain
	private static final double defaultIntensity = 1;
	
	// The texture set of the rain
	private final ResourceSet<Texture3D> textureSet;
	
	// The intensity of the rain
	private double intensity;
	
	// The sand box to which this rain is attached
	private SandBox box;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public SandBoxRain() {
		textureSet = Resources.getTextureSet("weather_rain");
		intensity = defaultIntensity;
		setInstance(new RainGenerator());
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	@Override public void setSize(double width, double height) {
		super.setSize(width, height);
	}
	
	/** Returns the intensity of the rain. **/
	public double getIntensity() {
		return intensity;
	}
	
	/** Sets the intensity of the rain. **/
	public void setIntensity(double intensity) {
		this.intensity = intensity;
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private final class RainGenerator extends SandBoxObject {
		
		private double regen;

		public RainGenerator() {
			super(WorldObject.onStep, 0);
		}

		@Override public void onAttach(SandBox box) {
			SandBoxRain.this.box = box;
			if (getWidth() <= 0 && getHeight() <= 0) {
				Rectangle r = new Rectangle();
				box.getBoundary(r);
				setSize(r.getWidth(),r.getHeight());
			}
		}

		@Override public void onDetach(SandBox box) {
			SandBoxRain.this.box = null;
		}

		@Override public SandBoxIcon createIcon() {
			return null;
		}

		@Override public void onStep(WorldArea world) {
			if (regen >= 1) {
				int rains = (int) regen;
				for (int i = 0; i < rains; i++) {
					Rain rain = new Rain();
					rain.setPosition(getX() + getWidth() * (-0.5 +  Math.random()), getY());
					box.addItem(rain);
				}
				regen -= rains;
			} else
				regen += intensity;
		}
		
	}
	
	private final class Rain extends WorldObject implements SandBoxItem {
		
		private double x, y;
		
		public Rain() {
			super(WorldObject.onStep + WorldObject.onPostDraw, depth);
		}

		@Override public void onAttach(SandBox box) {
			box.getWorld().createInstance(this);
		}

		@Override public void onDetach(SandBox box) {
			box.getWorld().destroyInstance(this);
		}

		@Override public SandBoxIcon createIcon() {
			return null;
		}

		@Override public void onStep(WorldArea world) {
			double y = getY();
			if (y > SandBoxRain.this.getY() + SandBoxRain.this.getHeight()) {
				if (box == null)
					world.destroyInstance(this);
				else
					box.removeItem(this);
			} else
				setPosition(getX(), y + 4);
		}
		
		@Override public void onPostDraw(WorldArea world, WorldCameraPane hud) {
			hud.drawImage(textureSet.get(0).getImage(), (int) x, (int) y);
		}

		@Override public boolean draggable() {
			return false;
		}

		@Override public boolean droppable() {
			return false;
		}

		@Override public void setPosition(double x, double y) {
			this.x = x;
			this.y = y;
		}

		@Override public double getX() {
			return x;
		}

		@Override public double getY() {
			return y;
		}

		@Override public double getWidth() {
			return 0;
		}

		@Override public double getHeight() {
			return 0;
		}
		
	}

}
